<?php
/**
 * Created by PhpStorm.
 * User: skytop
 * Date: 2017/1/18
 * Time: 12:58
 */
header("Content-type:text/html;charset=utf-8;");
//[数据存储于检索]

//保存数据以便后期使用
#存储数据有两种基本方法:保存到普通文件(flat file),或保存到数据库中

//文件处理
#将数据写入一个文件,有以下3步骤
/* 1.打开这个文件.如果文件不存在,需创建它.
 * 2.将数据写入这个文件
 * 3.关闭这个文件
 * */

#从一个文件中读取数据,也有三步:
/* 1.打开这个文件.如果这个文件不能打开(例如文件不存在),就应该意识到这一点并且正确的退出
 * 2.从文件中读取数据
 * 3.关闭这个文件
 * */

//打来文件
#要在PHP中打开一个文件,可使用fopen()函数.当打开一个文件的时候,还需指定如何使用它,也就是文件模式

#[选择文件模式]
#1.服务器上的操作系统必须知道要对打开的文件进行什么操作.
#2.操作系统需要了解在打开这个文件后,这个文件是否还允许其他脚本再打开.
#3.操作系统还需了解使用者(或脚本属主)是否具有在这种方式下使用该文件的权限.

#[当打开一个文件的时候,有以下三种选择]
#1.打开文件为了只读,只写或者读和写
#2.如果要写一个文件,你可能希望覆盖所有已有的文件内容,或者仅仅将新数据追加到文件末尾.如果该文件已经存在,也可以终止程序的执行而不是覆盖该文件.
#3.如果希望在一个区分了二进制方式和纯文本方式的系统上写一个文件,还必须制定采用的方式

##函数fopen()支持以上三种方式的组合

#使用fopen()打开文件

#resource fopen(string $filename,string $mode [,bool $use_include_path=false[,resource $context]])

/* filename:如果filename是"scheme://..."的格式,则被当成一个URL,PHP将搜索协议处理器(也被称为封装协议)来处理此模式.如果该协议尚未注册封装协议
 *mode参数指定了所要求到该流的访问类型.
 *  b:二进制模式(不知道做什么的,总之加上应该不会错)
 *
 *后面两个不常用
 * */

//假设要将一个顾客订单写入Bob的订单文件中,可以使用如下所示的语句打开这个文件:
#$fp=fopen("$DOCUMENT_ROOT/.../orders/orders.txt",'w');
/*$document_root=$_SERVER['DOCUMENT_ROOT'];
$fp=fopen("$document_root/order.txt",'x');*/

#写文件
//在PHP中写文件相对比较简单,可以使用fwrite()(file write,文件写)或者fputs()(file put string),fputs()是fwrite()别名
#int fwrite(resource handle,string string,[int length]);
#也可以用file_put_contents

/*$handle=fopen("{$_SERVER['DOCUMENT_ROOT']}/order.txt","w");
fwrite($handle,"abcde你好");*/

#关闭文件
//当使用完文件后,应该将其关闭.关闭一个已打开的文件指针使用fclose()
##如果该文件被成功关闭,函数将返回true,反之为false.通常关闭文件不容易出错,所以不用对操作进行测试.
#bool fclose(resource $handle)

//读取文件
#以只读模式打开文件
#fopen(string filename,"rb")

#feof()--测试文件指针是否到了文件结束的位置
##bool feof(resource $handle)
###handle:文件指针必须是有效的,必须指向由fopen()或fsockopen()成功打开的文件,并且未被fclose()关闭
###返回值:没看懂

#fgets()
//从文件指针中读取一行(读取一行都是从上到下读,调用一次函数读取一行)
#string fgets(resource $handle[,int $length])
$handle=fopen("{$_SERVER['DOCUMENT_ROOT']}/order.txt","rb");
echo "fgets()函数返回值为:".fgets($handle);
#fgetss()
//从文件指针中读取一行并过滤HTML标记和PHP标记(脚本语言直接过滤)
#string fgetss(resource $handle[,int $length[,string $allowable_tags]])
echo "<hr/>fgetss()函数实验:<br/>";
echo "fgetss()函数返回值为:".fgetss($handle)."<br/>";
echo "fgetss()函数返回值为:".fgetss($handle);

//从文件中截取字符串一行
#fgetcsv()---------[不太明白做什么用的][制表符?分隔?到底做啥的](原来第三个参数可以为分界点,以此符为分界作用制作出数组)
//从文件指针中读入一行并解析CSV字段,解析读入的行并找出CSV格式的字段然后返回一个包含这些字段的数组
#array fgetcsv(resource $handle[,int $length=0[,string $delimiter=","[,string $enclosure='"' [,string $escape="\\"]]]])
/* handle
 * length必须大于CVS文件内最长的一行,如果忽略则设为0
 * delimiter设置字段分解符(只允许一个字符)
 * enclosure设置字段环绕符(只允许一个字符)
 * escape设置转义字符(只允许一个字符),默认为一个反斜杠
 * */

echo "<hr/>";
var_dump(fgetcsv($handle,0, "d"));

#readfile()
//输出文件--------php脚本不会显示出来?应该是吧,HTML会显示出来效果
#int readfile(string $filename[,bool $use_include_path=false[,resource $context]])
/* filename:读取文件名
 * use_include_path:想要在include_path中搜索文件,可使用这个可选的第二个参数,设为true
 * context:stream上下文resource
 * */
echo "<hr/>readfile()输出结果:<br/>";
readfile("{$_SERVER['DOCUMENT_ROOT']}/order.txt");

#fpassthru()
//输出文件指针处的所有剩余数据---------将给定的文件指针从当前位置读取到EOF(end of file)并把结果写到输出缓冲区
#int fpassthru(resource $handle)
echo "<hr/>fpassthru()输出结果:<br/>";
rewind($handle);
var_dump(fpassthru($handle));
//返回从handle读取并传递到输出的字符数目(输出文件流和字符数目)

echo "<hr/>";
#file()
//把整个文件读入一个数组中 PS:你可以通过file_get_contents()以字符串形式获取文件的内容
#array file(string $filename[,int $flags=0[,resource $context]])
var_dump(file("{$_SERVER['DOCUMENT_ROOT']}/order.txt"));
//返回文件数组,数组元素代表一行数据(例子是这样,不知道对不对.php文档是英文,不知道啥意思)

#fgetc
//从文件指针中读取字符 | 从文件句柄中获取一个字符
#string fgetc(resource $handle)
//rewind($handle);    //若文件指针在末尾则读不出数据,即碰到EOF则返回false,但也可能返回的是等同于false的非布尔值,所以判断是否存在则要用到全等(===false)
var_dump(fgetc($handle));
#fread()
//读取文件(可安全用于二进制文件)
#string fread(resource $handle,int $length)
/*
 * fread()从文件指针handle读取最多length个字节.该函数在以下情况停止:
 *  1.读取了length个字节
 *  2.到达了文件末尾(EOF)
 *  3.都是英文...
 *
 * 返回所读取的字符串,或者在失败时返回false
 * */
echo "<hr/>fread()返回结果:<br/>";
rewind($handle);
echo fread($handle,2);

//查询文件是否存在
#file_exists()
//检查文件或目录是否存在
#bool file_exists(string $filename)
/*[filename]
 * 在windows中要用//computername/share/filename | \\computername\share\filename
 * 若果有filename指定的文件或目录存在返回true反之为false
 * */
echo "<hr/>file_exists()函数检测:<br/>";
echo $_SERVER['DOCUMENT_ROOT']."<br/>";
var_dump(file_exists("{$_SERVER['DOCUMENT_ROOT']}/1.txt"));

//确定文件大小
#filesize()
#int filesize(string $filename);
echo "<hr/>filesize()文件大小为:<br/>";
echo filesize("{$_SERVER['DOCUMENT_ROOT']}/order.txt");

//删除一个文件
#unlink()
#bool unlink(string $filename[,resource $context])
//var_dump(unlink("{$_SERVER['DOCUMENT_ROOT']}/1.txt"));
//删除成功返回true反之为false,若不存在这个文件则会报错

//在文件中定位
#rewind()
//倒回文件指针的位置
#bool rewind(resource $handle)
var_dump(rewind($handle));
//成功返回true反之为false

#fseek()
//在文件指针中定位
#int fseek(resource $handle,int $offset[,int $whence=SEEK_SET])
fseek($handle,2);
fseek($handle,2);
echo "<hr/>用fseek设置位置[SEEK_SET]为:<br/>".fgetc($handle);
fseek($handle,2,SEEK_CUR); //0或1显示不出来,没搞懂
echo "<hr/>用fseek设置位置[SEEK_CUR]为:<br/>".fgetc($handle);
fseek($handle,-1,SEEK_END);
echo "<hr/>用fseek设置位置[SEEK_END]为:<br/>".fgetc($handle);
/*echo fseek($handle,100);*/ //成功返回但是文件指针不知道在哪,也无法返回一个字符
echo "<hr/>用fseek设置位置[若偏移位置超出文件字符]为:<br/>".fgetc($handle);
/*handle:必须由fopen()创建的resource(资源)
 *offset:偏移量(要移动到文件尾部之前的位置,需要给offset传递一个负值,并设置whence为SEEK_END)
 * whence:
 *  1.SEEK_SET  设置位置等于offset字节
 *  2.SEEK_CUR  设置位置为当前位置奖赏offset
 *  3,SEEK_END  设置位置为文件尾加上offset
 *
 * 返回值:成功返回0;否则返回-1.注意:移到EOF之后的位置不算错误
 * Note:如果使用附加模式(a|a+),任何写入文件数据都会被附加上去,而文件的位置将会被忽略,调用fseek()结果尚未定义
 * */

#ftell()
//返回文件指针读/写的位置
#int ftell(resource $handle)
echo "<hr/>返回文件读写位置:<br/>".ftell($handle); //原来fseek()函数偏移量超过文件字符数则文件指针移到文件尾部
//返回由handle指定的文件指针的位置,也就是文件流中的偏移量,在附加模式(a|a+)中ftell()会返回未定义错误

//文件锁定
#flock()------不知道干什么的,所以没写例子
//轻便的咨询文件锁定(什么意思?)
#bool flock(resource $handle,int $operation[,int &$wouldblock])
//在php5.3.2版本之前,锁会被fclose()释放(在脚本结束后会自动调用)
//PHP支持以咨询方式(也就是说所有访问程序必须使用同一方式锁定,否则它不会工作)锁定全部文件的一种轻便方法.默认情况下,这个函数阻塞到获取锁;这可以通过下面文档中LOCK_NB选项来控制(在非windows平台上)
/*operation:
 *  1.LOCK_SH:取得共享锁(读取的程序)
 *  2.LOCK_EX:取得独占锁定(写入的程序)
 *  3.LOCK_UN:释放锁定(无论共享或者独占)[windows还不支持]
 * wouldblock:
 *  如果锁定会堵塞的话(EWOULDBLOCK错误情况下),可选的第三个参数会被设为true[windows不支持]
 * */

//更好的方式:数据库管理系统
#使用普通文件的几个问题
/*
 * 1.当文件变大时,使用普通文件将会变得很慢
 * 2.在一个普通文件中查找特定的一个或者一组记录将会非常困难
 * 3.处理并发访问可能会遇到问题
 * 4.到目前为止,我们所看到的文件处理都是顺序的文件处理---也就是我们从文件开始处一直读到文件的结尾.我们想在中间插入或删除文件非常困难
 * 5.除了使用文件访问权限外,还没有一个简单的方法可以区分不同级别的数据访问
 * */

#RDBMS是如何解决这些问题的
/*
 * 1.提供了比普通文件更快的数据访问.
 * 2.可以很容易的查找并检索符合特定条件的数据集
 * 3.具有内置的处理并发访问的机制
 * 4.可以随机访问数据
 * 5.有内置的权限系统
 * */